﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    //存在async/await 、BackGroudWorker类以及TPL（任务并行库）。当然还有一些旧的模式来支持异步编程
    // 定义委托
    delegate long MyDel(int first, int second);
    internal class DemoInvoke
    {
        public static long Sum(int x, int y)
        {
            Console.WriteLine("------Inside Sum@{0}", DateTime.Now.ToString());
            Thread.Sleep(2000);
            return x + y;
        }

        public static void Test()
        {
            MyDel del = new MyDel(Sum);

            Console.WriteLine("Before BeginInvoke---@{0}", DateTime.Now.ToString());
            // 3和5是引用方法参数，两个null分别是Callback参数和State参数
            // iar是新线程的信息
            IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
            Console.WriteLine("After BeginInvoke@{0}", DateTime.Now.ToString());

            Console.WriteLine("Doing stuff@{0}", DateTime.Now.ToString());

            long result = del.EndInvoke(iar);
            Console.WriteLine("End Invoke@{0}", DateTime.Now.ToString());

            Console.WriteLine("After EndInvoke:  {0}", result);

            Console.ReadKey();

        }

        //等待-直到完成 (主动)
        public static void Demo1()
        {
            MyDel del = new MyDel(Sum);
            //开始执行异步方法
            IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
            //Do Something 耗时
            del.EndInvoke(iar);
        }

        //轮询模式 (主动)
        public static void Demo2()
        {
            MyDel del = new MyDel(Sum);
            //开始执行异步方法
            IAsyncResult iar = del.BeginInvoke(3, 5, null, null);
            //轮询开始
            while (!iar.IsCompleted)
            {
                //未完成，执行下面的语句
                for (long i = 0; i < 20000000; i++)
                    ;
            }
            //执行完成调用EndInvoke获取结果
            long result = del.EndInvoke(iar);
            Console.ReadKey();
        }

        //回调模式
        public static void Demo3()
        {
            MyDel del = new MyDel(Sum);
            //a.回调方法：
            //1) new AsyncCallback 对象
            //IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone1), null);

            //2) 直接传回调方法的名称
            //IAsyncResult iar = del.BeginInvoke(3, 5, CallWhenDone, null);

            //b.在回调方法中调用EndInvoke
            IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone2), del);
        }

        static void CallWhenDone1(IAsyncResult iar)
        {
            //AsyncResult ar = (AsyncResult)iar;
            //MyDel del = (MyDel)ar.AsyncDelegate;
            //回调方法中调用了EndInvoke
            //long result = del.EndInvoke(iar);
        }

        static void CallWhenDone2(IAsyncResult iar)
        {
            MyDel del = (MyDel)iar.AsyncState;//iar.AsyncState as MyDel;
            //回调方法中调用了EndInvoke
            long result = del.EndInvoke(iar);
        }
    }
}
